/********************************************************************************
Copyright (C) 2016  International Ltd.
Copyright (C) 2022 - 2023, Phytium Technology Co., Ltd. All rights reserved.<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

*******************************************************************************/

#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/ShellCommandLib.h>
#include <Library/ShellLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/PrintLib.h>
#include <Library/HiiLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/HiiPackageList.h>
#include <Protocol/ServiceBinding.h>
#include <Protocol/Mtftp4.h>
#include <Library/NetLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiHiiServicesLib.h>
#include <Library/IoLib.h>
#include <Library/PcdLib.h>
#include <OEMSvc.h>
#include <Protocol/Cpu.h>
#include <Library/CacheMaintenanceLib.h>
#include <Guid/GlobalVariable.h>
#include <Library/ArmSmcLib.h>
#include <Library/PhytiumSpiNorFlashLib.h>
#include <Library/PhytiumPowerControlLib.h>
#include <Library/ArmPlatformLib.h>
#include <Library/BaseCryptLib.h>
#define IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH   32
#define UPDATEBIOS_PROGRESS_SLIDER_STEPS         ((sizeof (mUpdateBiosProgressFrame) / sizeof (CHAR16)) - 3)
#define UPDATEBIOS_PROGRESS_MESSAGE_SIZE         ((sizeof (mUpdateBiosProgressFrame) / sizeof (CHAR16)) + 12)

#define NOR_FLASH_DEVICE_COUNT                   1
#define SPI_FLASH_BASE                           FixedPcdGet64 (PcdSpiFlashBase)
#define SPI_FLASH_SIZE                           FixedPcdGet64 (PcdSpiFlashSize)
#define SPI_CONTROLLER_BASE                      FixedPcdGet64 (PcdSpiControllerBase)
#define SPI_CONTROLLER_SIZE                      FixedPcdGet64 (PcdSpiControllerSize)

#define O_PARAMETER_BASE                         0x400000
#define PM_DEV_INTERFACE_OFFSET                  0x400
#define FLASH_WRITE_CMD_OFFSET                   0x10
#define FLASH_ERASER_CMD_OFFSET                  0x14
#define FLASH_PP_CMD_OFFSET                      0x18
#define CMD_WRITE                                0x0
#define CMD_ERASER                               0x1
#define CMD_PP                                   0x2

#define QSPI_ADDR_BASE                           0x28014000
#define FLASH_CAPACITY                           0x000
#define RD_CFG                                   0x004
#define WR_CFG                                   0x008
#define MTFTP_DEFAULT_BLKSIZE                    512
#define MTFTP_MIN_BLKSIZE                        8
#define MTFTP_MAX_BLKSIZE                        65464
#define MTFTP_DEFAULT_WINDOWSIZE                 1
#define MTFTP_MIN_WINDOWSIZE                     1
#define MTFTP_MAX_WINDOWSIZE                     64

STATIC UINTN                     mNorFlashControlBase;
STATIC UINT32                    mCmd_Write = 0x2;
STATIC UINT32                    mCmd_Eares = 0xD8;
STATIC UINT32                    mCmd_Pp = 0x6;
STATIC UINT32                    mCmd_Eares16= 0xDC;
STATIC UINT32                    mCmd_Write16= 0x12;


NOR_FLASH_DESCRIPTION_PHYTIUM mNorFlashDevices[NOR_FLASH_DEVICE_COUNT] = {
  {
    SPI_FLASH_BASE,   /* Device Base Address */
    SPI_FLASH_BASE,   /* Region Base Address */
    SIZE_1MB * 16,    /* Size */
    SIZE_64KB,        /* Block Size */
    {0xE7223039, 0x5836, 0x41E1, { 0xB5, 0x42, 0xD7, 0xEC, 0x73, 0x6C, 0x5E, 0x59 } }
  },
};

CONST CHAR16  ShellBiosUpdateFileName[] = L"ShellBiosUpdateCommand";
EFI_HANDLE    ShellBiosUpdateHiiHandle = NULL;
/*
   Constant strings and definitions related to the message indicating the amount of
   progress in the dowloading of a TFTP file.
*/

// Frame for the progression slider
STATIC CONST CHAR16 mUpdateBiosProgressFrame[] = L"[                                        ]";

STATIC CONST CHAR16 mUpdateBiosProgressDelete[] = L"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";

// Local File Handle
SHELL_FILE_HANDLE     mFileHandle;

// Path of the local file, Unicode encoded
CONST CHAR16         *mLocalFilePath;

STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
  {L"-i", TypeValue},
  {L"-l", TypeValue},
  {L"-r", TypeValue},
  {L"-c", TypeValue},
  {L"-t", TypeValue},
  {L"-s", TypeValue},
  {L"-w", TypeValue},
  {NULL , TypeMax}
  };


typedef struct {
  UINTN  FileSize;
  UINTN  DownloadedNbOfBytes;
  UINTN  LastReportedNbOfBytes;
} DOWNLOAD_CONTEXT;

typedef struct {
	UINT32 Flash_Index;
	UINT32 Flash_Write;
	UINT32 Flash_Erase;
	UINT32 Flash_Pp;
}FLASH_CMD_INFO;

EFI_MTFTP4_CONFIG_DATA DefaultMtftp4ConfigData = {
  TRUE,                             // Use default setting
  { { 0, 0, 0, 0 } },               // StationIp         - Not relevant as UseDefaultSetting=TRUE
  { { 0, 0, 0, 0 } },               // SubnetMask        - Not relevant as UseDefaultSetting=TRUE
  0,                                // LocalPort         - Automatically assigned port number.
  { { 0, 0, 0, 0 } },               // GatewayIp         - Not relevant as UseDefaultSetting=TRUE
  { { 0, 0, 0, 0 } },               // ServerIp          - Not known yet
  69,                               // InitialServerPort - Standard TFTP server port
  6,                                // TryCount          - The number of times to transmit request packets and wait for a response.
  4                                 // TimeoutValue      - Retransmission timeout in seconds.
};

/**
  Return the file name of the help text file if not using HII.

  @return The string pointer to the file name.
**/
STATIC
CONST CHAR16*
EFIAPI
ShellCommandGetManFileNameBiosUpdate (
  VOID
  )
{
  return ShellBiosUpdateFileName;
}

/**
  Check and convert the UINT16 option values of the 'tftp' command

  @param[in]  ValueStr  Value as an Unicode encoded string
  @param[out] Value     UINT16 value

  @return     TRUE      The value was returned.
  @return     FALSE     A parsing error occured.
**/
STATIC
BOOLEAN
StringToUint16 (
  IN   CONST CHAR16  *ValueStr,
  OUT  UINT16        *Value
  );

/**
  Get the name of the NIC.

  @param[in]   ControllerHandle  The network physical device handle.
  @param[in]   NicNumber         The network physical device number.
  @param[out]  NicName           Address where to store the NIC name.
                                 The memory area has to be at least
                                 IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH
                                 double byte wide.

  @return  EFI_SUCCESS  The name of the NIC was returned.
  @return  Others       The creation of the child for the Managed
                        Network Service failed or the opening of
                        the Managed Network Protocol failed or
                        the operational parameters for the
                        Managed Network Protocol could not be
                        read.
**/
STATIC
EFI_STATUS
GetNicName (
  IN   EFI_HANDLE  ControllerHandle,
  IN   UINTN       NicNumber,
  OUT  CHAR16      *NicName
  );

/**
  Create a child for the service identified by its service binding protocol GUID
  and get from the child the interface of the protocol identified by its GUID.

  @param[in]   ControllerHandle            Controller handle.
  @param[in]   ServiceBindingProtocolGuid  Service binding protocol GUID of the
                                           service to be created.
  @param[in]   ProtocolGuid                GUID of the protocol to be open.
  @param[out]  ChildHandle                 Address where the handler of the
                                           created child is returned. NULL is
                                           returned in case of error.
  @param[out]  Interface                   Address where a pointer to the
                                           protocol interface is returned in
                                           case of success.

  @return  EFI_SUCCESS  The child was created and the protocol opened.
  @return  Others       Either the creation of the child or the opening
                        of the protocol failed.
**/
STATIC
EFI_STATUS
CreateServiceChildAndOpenProtocol (
  IN   EFI_HANDLE  ControllerHandle,
  IN   EFI_GUID    *ServiceBindingProtocolGuid,
  IN   EFI_GUID    *ProtocolGuid,
  OUT  EFI_HANDLE  *ChildHandle,
  OUT  VOID        **Interface
  );

/**
  Close the protocol identified by its GUID on the child handle of the service
  identified by its service binding protocol GUID, then destroy the child
  handle.

  @param[in]  ControllerHandle            Controller handle.
  @param[in]  ServiceBindingProtocolGuid  Service binding protocol GUID of the
                                          service to be destroyed.
  @param[in]  ProtocolGuid                GUID of the protocol to be closed.
  @param[in]  ChildHandle                 Handle of the child to be destroyed.

**/
STATIC
VOID
CloseProtocolAndDestroyServiceChild (
  IN  EFI_HANDLE  ControllerHandle,
  IN  EFI_GUID    *ServiceBindingProtocolGuid,
  IN  EFI_GUID    *ProtocolGuid,
  IN  EFI_HANDLE  ChildHandle
  );

/**
  Worker function that gets the size in numbers of bytes of a file from a TFTP
  server before to download the file.

  @param[in]   Mtftp4    MTFTP4 protocol interface
  @param[in]   FilePath  Path of the file, ASCII encoded
  @param[out]  FileSize  Address where to store the file size in number of
                         bytes.

  @retval  EFI_SUCCESS      The size of the file was returned.
  @retval  EFI_UNSUPPORTED  The server does not support the "tsize" option.
  @retval  Others           Error when retrieving the information from the server
                            (see EFI_MTFTP4_PROTOCOL.GetInfo() status codes)
                            or error when parsing the response of the server.
**/
STATIC
EFI_STATUS
GetFileSize (
  IN   EFI_MTFTP4_PROTOCOL  *Mtftp4,
  IN   CONST CHAR8          *FilePath,
  OUT  UINTN                *FileSize
  );

/**
  Worker function that download the data of a file from a TFTP server given
  the path of the file and its size.

  @param[in]   Mtftp4         MTFTP4 protocol interface
  @param[in]   FilePath       Path of the file, Unicode encoded
  @param[in]   AsciiFilePath  Path of the file, ASCII encoded
  @param[in]   FileSize       Size of the file in number of bytes
  @param[in]   BlockSize      Value of the TFTP blksize option
  @param[in]   WindowSize     Value of the TFTP window size option

  @retval  EFI_SUCCESS           The file was downloaded.
  @retval  EFI_OUT_OF_RESOURCES  A memory allocation failed.
  @retval  Others                The downloading of the file from the server failed
                                 (see EFI_MTFTP4_PROTOCOL.ReadFile() status codes).

**/
STATIC
EFI_STATUS
DownloadFile (
  IN   EFI_MTFTP4_PROTOCOL  *Mtftp4,
  IN   CONST CHAR16         *FilePath,
  IN   CONST CHAR8          *AsciiFilePath,
  IN   UINTN                FileSize,
  IN   UINT16               BlockSize,
  IN   UINT16               WindowSize
  );

/**
  Update the progress of a file download
  This procedure is called each time a new TFTP packet is received.

  @param[in]  This       MTFTP4 protocol interface
  @param[in]  Token      Parameters for the download of the file
  @param[in]  PacketLen  Length of the packet
  @param[in]  Packet     Address of the packet

  @retval  EFI_SUCCESS  All packets are accepted.

**/
STATIC
EFI_STATUS
EFIAPI
CheckPacket (
  IN EFI_MTFTP4_PROTOCOL  *This,
  IN EFI_MTFTP4_TOKEN     *Token,
  IN UINT16               PacketLen,
  IN EFI_MTFTP4_PACKET    *Packet
  );




